import json
import re
from django.conf import settings
from django.contrib.auth import login, authenticate
from django.http import HttpResponse
from django.http import HttpResponseForbidden
from django.http import JsonResponse
from django.middleware import http
from django.shortcuts import render, redirect
from django.urls import reverse
from django.views import View
from QQLoginTool.QQtool import OAuthQQ
from django_redis import get_redis_connection

from apps.oauth import sinaweibopy3
from apps.oauth.models import OAuthQQUser, OAuthSinaUser
from apps.users.models import User
from utils.response_code import RETCODE

# (封装函数)判断是否绑定qqID
from utils.secret import SecretOauth


def is_bind_openid(openid,request):
    # 从表中查询openid
    try:
        qq_user = OAuthQQUser.objects.get(openid=openid)
    except Exception as e:
        # 不存在跳转到注册页面且绑定openid
        context = {'openid': 'openid'}
        return render(request,'oauth_callback.html',context)
    else:
        # 存在 保持登录  重定向到首页  返回带有cookie
        user = qq_user.user
        login(request,user)
        response = redirect(reverse("contents:index"))
        response.set_cookie('username', user.username, max_age=14 * 2 * 24 * 3600)
    return response



# 获取qq登录网址
class QQAuthURLView(View):

    def get(self,request):
        # 1 导包
        # 2 实例化对象 -----------认证参数(dev中配置qq选项)
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET, redirect_uri=settings.QQ_REDIRECT_URI, state=next)
        # 3 获取qq登录地址 返回给前端 JsonResponse
        login_url = oauth.get_qq_url()
        return JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'login_url': login_url})


# 判断是否绑定
class QQQauthCallbackView(View):

    def get(self, request):
        # 获取code
        code = request.GET.get('code')
        # 如果存在
        if not code:
            return HttpResponseForbidden('缺少code')
        # 2 实例化对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI)
        # 获取tokon
        token = oauth.get_access_token(code)
        # 获取openid
        openid = oauth.get_open_id(token)
        # 判断是否接收到openid)
        # return HttpResponse(openid)
        # # 4. 判断是否绑定openid
        response = is_bind_openid(openid, request)
        return response
    # def post(self,request):
    #     # 接收参数
    #     # 正则校验
    #     # 判断手机号是否存在
    #     # 存在验证密码
    #     # 不存在新建用户
    #     # 绑定openid 操作OAuthQQUser表---新建数据
    #     """美多商城用户绑定到openid"""
    #     # 接收参数
    #     mobile = request.POST.get('mobile')
    #     pwd = request.POST.get('password')
    #     sms_code_client = request.POST.get('sms_code')
    #     openid = request.POST.get('openid')
    #     if not all([mobile,pwd,sms_code_client]):
    #         return HttpResponseForbidden('缺少必传参数')
    #     # 判断手机号是否合法
    #     if not re.match(r'^1[3-9]\d{9}$', mobile):
    #         return HttpResponseForbidden('请输入正确的手机号码')
    #     # 判断密码是否合格
    #     if not re.match(r'^[0-9A-Za-z]{8,20}$', pwd):
    #         return HttpResponseForbidden('请输入8-20位的密码')
    #     # 判断短信验证码是否一致
    #     redis_conn = get_redis_connection('verify_code')
    #     sms_code_server = redis_conn.get('sms_%s' % mobile)
    #     if sms_code_server is None:
    #         return render(request, 'oauth_callback.html', {'sms_code_errmsg': '无效的短信验证码'})
    #     if sms_code_client != sms_code_server.decode():
    #         return render(request, 'oauth_callback.html', {'sms_code_errmsg': '输入短信验证码有误'})
    #         # 解密出openid 再判断openid是否有效
    #     openid = SecretOauth().loads(openid).get('openid')
    #     if not openid:
    #         return render(request, 'oauth_callback.html', {'openid_errmsg': '无效的openid'})
    #
    #     # 保存注册数据
    #     try:
    #         user = User.objects.get(mobile=mobile)
    #     except User.DoesNotExist:
    #         # 用户不存在,新建用户
    #         user = User.objects.create_user(username=mobile, password=pwd, mobile=mobile)
    #     else:
    #         # 如果用户存在，检查用户密码
    #         if not user.check_password(pwd):
    #             return render(request, 'oauth_callback.html', {'account_errmsg': '用户名或密码错误'})
    #
    #     # 将用户绑定openid
    #     try:
    #         OAuthQQUser.objects.create(openid=openid, user=user)
    #     except Exception as e:
    #         return render(request, 'oauth_callback.html', {'qq_login_errmsg': 'QQ登录失败'})
    #
    #     # 实现状态保持
    #     login(request, user)
    #
    #     # 响应绑定结果
    #     next = request.GET.get('state')
    #     response = redirect(next)
    #
    #     # 登录时用户名写入到cookie，有效期15天
    #     response.set_cookie('username', user.username, max_age=3600 * 24 * 15)
    #
    #     return response
    #     pass

# 获取微薄登录网址
class SinaLoginView(View):

    def get(self,request):
        # 1 导包
        next = request.GET.get("next")
        # 2 实例化对象 -----------认证参数(dev中配置qq选项)
        client = sinaweibopy3.APIClient(
        # app_key： app_key值
        app_key=settings.APP_KEY,
        # app_secret：app_secret 值
        app_secret=settings.APP_SECRET,
        # redirect_uri ： 回调地址
        redirect_uri=settings.REDIRECT_URL
        )
        login_url = client.get_authorize_url()
        return JsonResponse({'code': 'o', 'errmsg': '微博登录网址', 'login_url': login_url})

# 获取uid
class SinaCallbackView(View):
    def get(self,request):
        code = request.GET.get("code")
        client = sinaweibopy3.APIClient(
            # app_key： app_key值
            app_key=settings.APP_KEY,
            # app_secret：app_secret 值
            app_secret=settings.APP_SECRET,
            # redirect_uri ： 回调地址
            redirect_uri=settings.REDIRECT_URL
        )
        result = client.request_access_token(code)
        access_token = result.access_token
        uuid = result.uid
        # 判断是否用微薄登录过
        try:
            sina_user = OAuthSinaUser.objects.get(uid=uuid)
        except:
            uid = SecretOauth().dumps(uuid)
            return render(request, 'sina_callback.html', context={'uid': uid})
        user = sina_user.user
        # 保持登录状态
        login(request, user)
        # 设置首页用户名
        response = redirect(reverse('contents:index'))
        response.set_cookie('username', user.username, max_age=24 * 14 * 3600)
        # 重定向 首页
        return response

# 绑定用户提交
class SinaUserView(View):
    def post(self,request):
        json_str = request.body.decode()
        req_data = json.loads(json_str)
        try:
            uid = SecretOauth().loads(req_data["uid"])
        except:
            render(request, 'sina_callback.html', {'uid_errmsg': '无效的uid'})
        password = req_data["password"]
        sms_code = req_data["sms_code"]
        mobile = req_data["mobile"]
        user = request.user
        try:
            # # 取数据
            redis_code_client = get_redis_connection("sms_code")
            redis_code = redis_code_client.get("sms_%s" % mobile)
        except:
            render(request, 'sina_callback.html', {'sms_code_errmsg': '无效的短信验证码'})
        # 验证短信验证码是否正确;
        # 对比redis的值和前端的值
        if sms_code != redis_code.decode():
            render(request, 'sina_callback.html', {'sms_code_errmsg': '输入短信验证码有误'})

        # user = authenticate(username=user.username, password=password)
        # if user != True:
        #     render(request, 'sina_callback.html', {'account_errmsg': '用户名或密码错误'})
        try:
            user = User.objects.get(mobile = mobile)
        except:
            user = User.objects.create_user(username=mobile,mobile=mobile,password=password)
        else:
            if not user.check_password(password):
                render(request, 'sina_callback.html', {'account_errmsg': '用户名或密码错误'})

        OAuthSinaUser.objects.create(
            uid=uid,
            user=user
        )
        login(request, user)
        response = redirect(reverse('contents:index'))
        response.set_cookie('username', user.username, max_age=3600 * 24 * 15)
        # uid解密失败: render(request, 'sina_callback.html', {'uid_errmsg': '无效的uid'})
        # 短信失效: render(request, 'sina_callback.html', {'sms_code_errmsg': '无效的短信验证码'})
        # 短信输入有误: render(request, 'sina_callback.html', {'sms_code_errmsg': '输入短信验证码有误'})
        # 密码错误: render(request, 'sina_callback.html', {'account_errmsg': '用户名或密码错误'})
        return response